using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;


namespace Universe.WinForms.BitmapButtonUI
{
	/// <summary>
	/// possible button states
	/// </summary>
	public enum BtnState
	{
		/// <summary>
		/// The button is disabled.
		/// </summary>		
		Inactive = 0,
		/// <summary>
		/// The button is in it normal unpressed state
		/// </summary>
		Normal = 1,
		/// <summary>
		/// The location of the mouse is over the button
		/// </summary>
		MouseOver = 2,
		/// <summary>
		/// The button is currently being pressed
		/// </summary>
		Pushed = 3,
	}


	/// <summary>
	/// The purpose of this class is to continue to provide the regular functionality of button class with
	/// some additional bitmap enhancments. These enhancements allow the specification of bitmaps for each 
	/// state of the button. In addition, it makes use of the alignment properties already provided by the 
	/// base button class. Since this class renders the image, it should appear similar accross platforms.	
	/// </summary>
	public class BitmapButton : System.Windows.Forms.Button
	{
		#region Private Variables

		private System.Drawing.Image _ImageNormal = null;
		private System.Drawing.Image _ImageFocused = null;
		private System.Drawing.Image _ImagePressed = null;
		private System.Drawing.Image _ImageMouseOver = null;
		private System.Drawing.Image _ImageInactive = null;
		private System.Drawing.Color _BorderColor = System.Drawing.Color.DarkBlue;
		private System.Drawing.Color _InnerBorderColor = System.Drawing.Color.LightGray;
		private System.Drawing.Color _InnerBorderColor_Focus = System.Drawing.Color.LightBlue;
		private System.Drawing.Color _InnerBorderColor_MouseOver = System.Drawing.Color.Gold;
		private System.Drawing.Color _ImageBorderColor = System.Drawing.Color.Chocolate;
		private bool _StretchImage = false;
		private bool _TextDropShadow = true;
		private int _Padding = 5;
		private bool _OffsetPressedContent = true;
		private bool _ImageBorderEnabled = true;
		private bool _ImageDropShadow = true;
		private bool _FocusRectangleEnabled = true;
		private BtnState btnState = BtnState.Normal;
		private bool CapturingMouse = false;

		#endregion

		#region Public Properties

		[Browsable(false)]
		new public System.Drawing.Image Image
		{
			get { return base.Image; }
			set { base.Image = value; }
		}

		[Browsable(false)]
		new public System.Windows.Forms.ImageList ImageList
		{
			get { return base.ImageList; }
			set { base.ImageList = value; }
		}

		[Browsable(false)]
		new public int ImageIndex
		{
			get { return base.ImageIndex; }
			set { base.ImageIndex = value; }
		}

		/// <summary>
		/// Enable the shadowing of the button text
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("enables the text to cast a shadow")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public bool TextDropShadow
		{
			get { return _TextDropShadow; }
			set { _TextDropShadow = value; }
		}

		/// <summary>
		/// Enables the dashed focus rectangle
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("enables the focus rectangle")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public bool FocusRectangleEnabled
		{
			get { return _FocusRectangleEnabled; }
			set { _FocusRectangleEnabled = value; }
		}

		/// <summary>
		/// Enable the shadowing of the image in the button
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("enables the image to cast a shadow")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public bool ImageDropShadow
		{
			get { return _ImageDropShadow; }
			set { _ImageDropShadow = value; }
		}

		/// <summary>
		/// This specifies the color of image border. Note, this is only valid if ImageBorder is enabled.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Color of the border around the image")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Color ImageBorderColor
		{
			get { return _ImageBorderColor; }
			set { _ImageBorderColor = value; }
		}

		/// <summary>
		/// This enables/disables the bordering of the image.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Enables the bordering of the image")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public bool ImageBorderEnabled
		{
			get { return _ImageBorderEnabled; }
			set { _ImageBorderEnabled = value; }
		}

		/// <summary>
		/// Color of the border around the button
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Color of the border around the button")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Color BorderColor
		{
			get { return _BorderColor; }
			set { _BorderColor = value; }
		}

		/// <summary>
		/// Color of the inner border when the button has focus
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("Color of the inner border when the button has focus")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Color InnerBorderColor_Focus
		{
			get { return _InnerBorderColor_Focus; }
			set { _InnerBorderColor_Focus = value; }
		}

		/// <summary>
		/// Color of the inner border when the button does not have focus
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("Color of the inner border when the button does not hvae focus")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Color InnerBorderColor
		{
			get { return _InnerBorderColor; }
			set { _InnerBorderColor = value; }
		}

		/// <summary>
		/// Color of the inner border when the mouse is over the button.
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("color of the inner border when the mouse is over the button")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Color InnerBorderColor_MouseOver
		{
			get { return _InnerBorderColor_MouseOver; }
			set { _InnerBorderColor_MouseOver = value; }
		}

		/// <summary>
		/// Stretches the image across the button
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("stretch the impage to the size of the button")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public bool StretchImage
		{
			get { return _StretchImage; }
			set { _StretchImage = value; }
		}

		/// <summary>
		/// Specifies the padding in units of pixels around the button button elements. Currently,
		/// the button elements consist of the image and text.
		/// </summary>
		[Browsable(true)]
		[CategoryAttribute("Appearance")]
		[Description("padded pixels around the image and text")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public int Padding
		{
			get { return _Padding; }
			set { _Padding = value; }
		}

		/// <summary>
		/// Set to true if to offset button elements when button is pressed
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Set to true if to offset image/text when button is pressed")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public bool OffsetPressedContent
		{
			get
			{
				return
					_OffsetPressedContent;
			}
			set { _OffsetPressedContent = value; }
		}

		/// <summary>
		/// Image to be displayed while the button state is in normal state. If the other
		/// states do not specify an image, this image is used as a substitute.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Image to be displayed while the button state is in normal state")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Image ImageNormal
		{
			get { return _ImageNormal; }
			set { _ImageNormal = value; }
		}

		/// <summary>
		/// Specifies an image to use while the button has focus.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Image to be displayed while the button has focus")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Image ImageFocused
		{
			get { return _ImageFocused; }
			set { _ImageFocused = value; }
		}

		/// <summary>
		/// Specifies an image to use while the button is enactive.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Image to be displayed while the button is inactive")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Image ImageInactive
		{
			get { return _ImageInactive; }
			set { _ImageInactive = value; }
		}

		/// <summary>
		/// Specifies an image to use while the button is pressed.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Image to be displayed while the button state is pressed")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Image ImagePressed
		{
			get { return _ImagePressed; }
			set { _ImagePressed = value; }
		}

		/// <summary>
		/// Specifies an image to use while the mouse is over the button.
		/// </summary>
		[Browsable(true)
			]
		[CategoryAttribute("Appearance")]
		[Description("Image to be displayed while the button state is MouseOver")]
		[System.ComponentModel.RefreshProperties(RefreshProperties.Repaint)]
		public System.Drawing.Image ImageMouseOver
		{
			get { return _ImageMouseOver; }
			set { _ImageMouseOver = value; }
		}

		#endregion

		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		/// <summary>
		/// The BitmapButton constructor
		/// </summary>
		public BitmapButton()
		{
			// This call is required by the Windows.Forms Form Designer.
			InitializeComponent();
			// TODO: Add any initialization after the InitComponent call			

			//LoadGraphics();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose(bool disposing)
		{
			if (disposing)
			{
				if (components != null)
					components.Dispose();
			}
			base.Dispose(disposing);
		}

		#region Component Designer generated code

		/// <summary>
		/// Required method for Designer support - do not modify 
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			components = new System.ComponentModel.Container();
		}

		#endregion

		#region Paint Methods

		/// <summary>
		/// This method paints the button in its entirety.
		/// </summary>
		/// <param name="e">paint arguments use to paint the button</param>
		protected override void OnPaint(PaintEventArgs e)
		{
			CreateRegion(0);
			paint_Background(e);
			paint_Text(e);
			paint_Image(e);
			paint_Border(e);
			paint_InnerBorder(e);
			paint_FocusBorder(e);
		}

		/// <summary>
		/// This method fills the background of the button.
		/// </summary>
		/// <param name="e">paint arguments use to paint the button</param>
		private void paint_Background(PaintEventArgs e)
		{
			if (e == null)
				return;
			if (e.Graphics == null)
				return;

			Graphics g = e.Graphics;
			System.Drawing.Rectangle rect = new Rectangle(0, 0, Size.Width, Size.Height);
			//
			// get color of background
			//			
			System.Drawing.Color color = this.BackColor;
			;
			if (btnState == BtnState.Inactive)
				color = System.Drawing.Color.LightGray;
			//
			// intialize ColorArray and Positions Array
			//
			Color[] ColorArray = null;
			float[] PositionArray = null;
			//
			// initialize color array for a button that is pushed
			//			
			if (btnState == BtnState.Pushed)
			{
				ColorArray = new Color[]
					{
						Blend(this.BackColor, System.Drawing.Color.White, 80),
						Blend(this.BackColor, System.Drawing.Color.White, 40),
						Blend(this.BackColor, System.Drawing.Color.Black, 0),
						Blend(this.BackColor, System.Drawing.Color.Black, 0),
						Blend(this.BackColor, System.Drawing.Color.White, 40),
						Blend(this.BackColor, System.Drawing.Color.White, 80),
					};
				PositionArray = new float[] {0.0f, .05f, .40f, .60f, .95f, 1.0f};
			}
				//
				// else, initialize color array for a button that is normal or disabled
				//			
			else
			{
				ColorArray = new Color[]
					{
						Blend(color, System.Drawing.Color.White, 80),
						Blend(color, System.Drawing.Color.White, 90),
						Blend(color, System.Drawing.Color.White, 30),
						Blend(color, System.Drawing.Color.White, 00),
						Blend(color, System.Drawing.Color.Black, 30),
						Blend(color, System.Drawing.Color.Black, 20),
					};
				PositionArray = new float[] {0.0f, .15f, .40f, .65f, .80f, 1.0f};
			}
			//
			// create blend variable for the interpolate the colors
			//
			System.Drawing.Drawing2D.ColorBlend blend = new System.Drawing.Drawing2D.ColorBlend();
			blend.Colors = ColorArray;
			blend.Positions = PositionArray;
			//
			// create vertical gradient brush
			//
			System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, this.BackColor, Blend(this.BackColor, this.BackColor, 10), System.Drawing.Drawing2D.LinearGradientMode.Vertical);
			brush.InterpolationColors = blend;
			//
			// fill the rectangle
			//
			g.FillRectangle(brush, rect);
			//
			// release resources
			//
			brush.Dispose();
		}

		/// <summary>
		/// paints the 1 pixel border around the button. The color of
		/// the border is defined by BorderColor
		/// </summary>
		/// <param name="e">paint arguments use to paint the button</param>
		private void paint_Border(PaintEventArgs e)
		{
			if (e == null)
				return;
			if (e.Graphics == null)
				return;
			//
			// create the pen
			//
			Pen pen = new Pen(this.BorderColor, 1);
			//
			// get the points for the border
			//
			Point[] pts = border_Get(0, 0, this.Width - 1, this.Height - 1);
			//
			// paint the border
			//
			e.Graphics.DrawLines(pen, pts);
			//
			// release resources
			//
			pen.Dispose();
		}

		/// <summary>
		/// paints the focus rectangle. 
		/// </summary>
		/// <param name="e">paint arguments use to paint the button</param>		 
		private void paint_FocusBorder(PaintEventArgs e)
		{
			if (e == null)
				return;
			if (e.Graphics == null)
				return;
			//
			// if the button has focus, and focus rectangle is enabled,
			// draw the focus box
			//
			if (this.Focused)
			{
				if (FocusRectangleEnabled)
					ControlPaint.DrawFocusRectangle(e.Graphics, new Rectangle(3, 3, this.Width - 6, this.Height - 6), System.Drawing.Color.Black, this.BackColor);
			}
		}

		/// <summary>
		/// paint the inner border of the button.
		/// </summary>
		/// <param name="e">paint arguments use to paint the button</param>		 
		private void paint_InnerBorder(PaintEventArgs e)
		{
			if (e == null)
				return;
			if (e.Graphics == null)
				return;

			Graphics g = e.Graphics;
			System.Drawing.Rectangle rect = new Rectangle(0, 0, Size.Width, Size.Height);

			System.Drawing.Color color = this.BackColor;
			//
			// get color of inner border
			//
			switch (btnState)
			{
				case BtnState.Inactive:
					color = System.Drawing.Color.Gray;
					break;
				case BtnState.Normal:
					if (this.Focused)
						color = this.InnerBorderColor_Focus;
					else
						color = this.InnerBorderColor;
					break;
				case BtnState.Pushed:
					color = Blend(InnerBorderColor_Focus, System.Drawing.Color.Black, 10);
					break;
				case BtnState.MouseOver:
					color = InnerBorderColor_MouseOver;
					break;
			}
			//
			// populate color and position arrays
			//			
			Color[] ColorArray = null;
			float[] PositionArray = null;
			if (btnState == BtnState.Pushed)
			{
				ColorArray = new System.Drawing.Color[]
					{
						Blend(color, System.Drawing.Color.Black, 20),
						Blend(color, System.Drawing.Color.Black, 10),
						Blend(color, System.Drawing.Color.White, 00),
						Blend(color, System.Drawing.Color.White, 50),
						Blend(color, System.Drawing.Color.White, 85),
						Blend(color, System.Drawing.Color.White, 90),
					};
				PositionArray = new float[] {0.0f, .20f, .50f, .60f, .90f, 1.0f};
			}
			else
			{
				ColorArray = new System.Drawing.Color[]
					{
						Blend(color, System.Drawing.Color.White, 80),
						Blend(color, System.Drawing.Color.White, 60),
						Blend(color, System.Drawing.Color.White, 10),
						Blend(color, System.Drawing.Color.White, 00),
						Blend(color, System.Drawing.Color.Black, 20),
						Blend(color, System.Drawing.Color.Black, 50),
					};
				PositionArray = new float[] {0.0f, .20f, .50f, .60f, .90f, 1.0f};
			}
			//
			// create blend object
			//
			System.Drawing.Drawing2D.ColorBlend blend = new System.Drawing.Drawing2D.ColorBlend();
			blend.Colors = ColorArray;
			blend.Positions = PositionArray;
			//
			// create gradient brush and pen
			//
			System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, this.BackColor, Blend(this.BackColor, this.BackColor, 10), System.Drawing.Drawing2D.LinearGradientMode.Vertical);
			brush.InterpolationColors = blend;
			System.Drawing.Pen pen0 = new System.Drawing.Pen(brush, 1);
			//
			// get points array to draw the line
			//
			Point[] pts = border_Get(0, 0, this.Width - 1, this.Height - 1);
			//
			// draw line 0
			//
			this.border_Contract(1, ref pts);
			e.Graphics.DrawLines(pen0, pts);
			//
			// draw line 1
			//			
			this.border_Contract(1, ref pts);
			e.Graphics.DrawLines(pen0, pts);
			//
			// release resources
			//
			pen0.Dispose();
			brush.Dispose();
		}

		/// <summary>
		/// This method paints the text and text shadow for the button.
		/// </summary>
		/// <param name="e">paint arguments use to paint the button</param>		 
		private void paint_Text(PaintEventArgs e)
		{
			if (e == null)
				return;
			if (e.Graphics == null)
				return;
			System.Drawing.Rectangle rect = GetTextDestinationRect();
			//
			// do offset if button is pushed
			//
			if ((btnState == BtnState.Pushed) && (OffsetPressedContent))
				rect.Offset(1, 1);
			//
			// caculate bounding rectagle for the text
			//
			System.Drawing.SizeF size = txt_Size(e.Graphics, this.Text, this.Font);
			//
			// calculate the starting location to paint the text
			//
			System.Drawing.Point pt = Calculate_LeftEdgeTopEdge(this.TextAlign, rect, (int) size.Width, (int) size.Height);
			//
			// If button state is inactive, paint the inactive text
			//
			if (btnState == BtnState.Inactive)
			{
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(System.Drawing.Color.White), pt.X + 1, pt.Y + 1);
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(System.Drawing.Color.FromArgb(50, 50, 50)), pt.X, pt.Y);
			}
				//
				// else, paint the text and text shadow
				//
			else
			{
				//
				// paint text shadow
				//
				if (TextDropShadow)
				{
					System.Drawing.Brush TransparentBrush0 = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(50, System.Drawing.Color.Black));
					System.Drawing.Brush TransparentBrush1 = new System.Drawing.SolidBrush(System.Drawing.Color.FromArgb(20, System.Drawing.Color.Black));

					e.Graphics.DrawString(this.Text, this.Font, TransparentBrush0, pt.X, pt.Y + 1);
					e.Graphics.DrawString(this.Text, this.Font, TransparentBrush0, pt.X + 1, pt.Y);

					e.Graphics.DrawString(this.Text, this.Font, TransparentBrush1, pt.X + 1, pt.Y + 1);
					e.Graphics.DrawString(this.Text, this.Font, TransparentBrush1, pt.X, pt.Y + 2);
					e.Graphics.DrawString(this.Text, this.Font, TransparentBrush1, pt.X + 2, pt.Y);

					TransparentBrush0.Dispose();
					TransparentBrush1.Dispose();
				}
				//
				// paint text
				//
				e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), pt.X, pt.Y);
			}
		}

		/// <summary>
		/// Paints a border around the image. If Image drop shadow is enabled,
		/// a shodow is drawn too.
		/// </summary>
		/// <param name="g">The graphics object</param>
		/// <param name="ImageRect">the rectangle region of the image</param>
		private void paint_ImageBorder(System.Drawing.Graphics g, System.Drawing.Rectangle ImageRect)
		{
			System.Drawing.Rectangle rect = ImageRect;

			//
			// If ImageDropShadow = true, draw shadow
			//
			if (ImageDropShadow)
			{
				System.Drawing.Pen p0 = new System.Drawing.Pen(System.Drawing.Color.FromArgb(80, 0, 0, 0));
				System.Drawing.Pen p1 = new System.Drawing.Pen(System.Drawing.Color.FromArgb(40, 0, 0, 0));
				g.DrawLine(p0, new Point(rect.Right, rect.Bottom), new Point(rect.Right + 1, rect.Bottom));
				g.DrawLine(p0, new Point(rect.Right + 1, rect.Top + 1), new Point(rect.Right + 1, rect.Bottom + 0));
				g.DrawLine(p1, new Point(rect.Right + 2, rect.Top + 2), new Point(rect.Right + 2, rect.Bottom + 1));
				g.DrawLine(p0, new Point(rect.Left + 1, rect.Bottom + 1), new Point(rect.Right + 0, rect.Bottom + 1));
				g.DrawLine(p1, new Point(rect.Left + 1, rect.Bottom + 2), new Point(rect.Right + 1, rect.Bottom + 2));
			}
			//
			// Draw Image Border
			//
			if (ImageBorderEnabled)
			{
				Color[] ColorArray = null;
				float[] PositionArray = null;
				System.Drawing.Color color = this.ImageBorderColor;
				if (!this.Enabled)
					color = System.Drawing.Color.LightGray;
				//
				// initialize color and position array
				//
				ColorArray = new Color[]
					{
						Blend(color, System.Drawing.Color.White, 40),
						Blend(color, System.Drawing.Color.White, 20),
						Blend(color, System.Drawing.Color.White, 30),
						Blend(color, System.Drawing.Color.White, 00),
						Blend(color, System.Drawing.Color.Black, 30),
						Blend(color, System.Drawing.Color.Black, 70),
					};
				PositionArray = new float[] {0.0f, .20f, .50f, .60f, .90f, 1.0f};
				//
				// create blend object
				//
				System.Drawing.Drawing2D.ColorBlend blend = new System.Drawing.Drawing2D.ColorBlend();
				blend.Colors = ColorArray;
				blend.Positions = PositionArray;
				//
				// create brush and pens
				//
				System.Drawing.Drawing2D.LinearGradientBrush brush = new System.Drawing.Drawing2D.LinearGradientBrush(rect, this.BackColor, Blend(this.BackColor, this.BackColor, 10), System.Drawing.Drawing2D.LinearGradientMode.Vertical);
				brush.InterpolationColors = blend;
				System.Drawing.Pen pen0 = new System.Drawing.Pen(brush, 1);
				System.Drawing.Pen pen1 = new System.Drawing.Pen(System.Drawing.Color.Black);
				//
				// calculate points to draw line
				//
				rect.Inflate(1, 1);
				Point[] pts = border_Get(rect.Left, rect.Top, rect.Width, rect.Height);
				this.border_Contract(1, ref pts);
				//
				// draw line 0
				//
				g.DrawLines(pen1, pts);
				//
				// draw line 1
				//
				this.border_Contract(1, ref pts);
				g.DrawLines(pen0, pts);
				//
				// release resources
				//
				pen1.Dispose();
				pen0.Dispose();
				brush.Dispose();
			}
		}

		/// <summary>
		/// Paints the image on the button.
		/// </summary>
		/// <param name="e"></param>
		private void paint_Image(PaintEventArgs e)
		{
			if (e == null)
				return;
			if (e.Graphics == null)
				return;
			Image image = GetCurrentImage(btnState);

			if (image != null)
			{
				Graphics g = e.Graphics;
				System.Drawing.Rectangle rect = GetImageDestinationRect();

				if ((btnState == BtnState.Pushed) && (_OffsetPressedContent))
					rect.Offset(1, 1);
				if (this.StretchImage)
					g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
				else
				{
					System.Drawing.Rectangle r = GetImageDestinationRect();
					//g.DrawImage(image,rect.Left,rect.Top);
					g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);
				}
				paint_ImageBorder(g, rect);
			}
		}

		#endregion

		#region Helper Methods

		/// <summary>
		/// Calculates the required size to draw a text string
		/// </summary>
		/// <param name="g">the graphics object</param>
		/// <param name="strText">string to calculate text region</param>
		/// <param name="font">font to use for the string</param>
		/// <returns>returns the size required to draw a text string</returns>
		private System.Drawing.SizeF txt_Size(Graphics g, string strText, Font font)
		{
			System.Drawing.SizeF size = g.MeasureString(strText, font);
			return (size);
		}

		/// <summary>
		/// Calculates the rectangular region used for text display.
		/// </summary>
		/// <returns>returns the rectangular region for the text display</returns>
		private System.Drawing.Rectangle GetTextDestinationRect()
		{
			System.Drawing.Rectangle ImageRect = GetImageDestinationRect();
			System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, 0, 0);
			switch (this.ImageAlign)
			{
				case System.Drawing.ContentAlignment.BottomCenter:
					rect = new System.Drawing.Rectangle(0, 0, this.Width, ImageRect.Top);
					break;
				case System.Drawing.ContentAlignment.BottomLeft:
					rect = new System.Drawing.Rectangle(0, 0, this.Width, ImageRect.Top);
					break;
				case System.Drawing.ContentAlignment.BottomRight:
					rect = new System.Drawing.Rectangle(0, 0, this.Width, ImageRect.Top);
					break;
				case System.Drawing.ContentAlignment.MiddleCenter:
					rect = new System.Drawing.Rectangle(0, ImageRect.Bottom, this.Width, this.Height - ImageRect.Bottom);
					break;
				case System.Drawing.ContentAlignment.MiddleLeft:
					rect = new System.Drawing.Rectangle(ImageRect.Right, 0, this.Width - ImageRect.Right, this.Height);
					break;
				case System.Drawing.ContentAlignment.MiddleRight:
					rect = new System.Drawing.Rectangle(0, 0, ImageRect.Left, this.Height);
					break;
				case System.Drawing.ContentAlignment.TopCenter:
					rect = new System.Drawing.Rectangle(0, ImageRect.Bottom, this.Width, this.Height - ImageRect.Bottom);
					break;
				case System.Drawing.ContentAlignment.TopLeft:
					rect = new System.Drawing.Rectangle(0, ImageRect.Bottom, this.Width, this.Height - ImageRect.Bottom);
					break;
				case System.Drawing.ContentAlignment.TopRight:
					rect = new System.Drawing.Rectangle(0, ImageRect.Bottom, this.Width, this.Height - ImageRect.Bottom);
					break;
			}
			rect.Inflate(-this.Padding, -this.Padding);
			return (rect);
		}

		/// <summary>
		/// Calculates the rectangular region used for image display.
		/// </summary>
		/// <returns>returns the rectangular region used to display the image</returns>
		private System.Drawing.Rectangle GetImageDestinationRect()
		{
			System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, 0, 0);
			System.Drawing.Image image = GetCurrentImage(this.btnState);
			if (image != null)
			{
				if (this.StretchImage)
				{
					rect.Width = this.Width;
					rect.Height = this.Height;
				}
				else
				{
					rect.Width = image.Width;
					rect.Height = image.Height;
					System.Drawing.Rectangle drect = new System.Drawing.Rectangle(0, 0, this.Width, this.Height);
					drect.Inflate(-this.Padding, -this.Padding);
					System.Drawing.Point pt = Calculate_LeftEdgeTopEdge(this.ImageAlign, drect, image.Width, image.Height);
					rect.Offset(pt);
				}
			}
			return (rect);
		}

		/// <summary>
		/// This method is used to retrieve the image used by the button for the given state.
		/// </summary>
		/// <param name="btnState">holds the state of the button</param>
		/// <returns>returns the button Image</returns>
		private System.Drawing.Image GetCurrentImage(BtnState btnState)
		{
			System.Drawing.Image image = ImageNormal;
			switch (btnState)
			{
				case BtnState.Normal:
					if (this.Focused)
					{
						if (this.ImageFocused != null)
							image = this.ImageFocused;
					}
					break;
				case BtnState.MouseOver:
					if (ImageMouseOver != null)
						image = ImageMouseOver;
					break;
				case BtnState.Pushed:
					if (ImagePressed != null)
						image = ImagePressed;
					break;
				case BtnState.Inactive:
					if (ImageInactive != null)
						image = ImageInactive;
					else
					{
						if (image != null)
							ImageInactive = ConvertToGrayscale(new Bitmap(ImageNormal));
						image = ImageNormal;
					}
					break;
			}
			return (image);
		}

		/// <summary>
		/// converts a bitmap image to grayscale
		/// </summary>
		/// <param name="source">bitmap source</param>
		/// <returns>returns a grayscaled bitmap</returns>
		public Bitmap ConvertToGrayscale(Bitmap source)
		{
			Bitmap bm = new Bitmap(source.Width, source.Height);
			for (int y = 0; y < bm.Height; y++)
			{
				for (int x = 0; x < bm.Width; x++)
				{
					Color c = source.GetPixel(x, y);
					int luma = (int) (c.R*0.3 + c.G*0.59 + c.B*0.11);
					bm.SetPixel(x, y, Color.FromArgb(luma, luma, luma));
				}
			}
			return bm;
		}

		/// <summary>
		/// calculates the left/top edge for content.
		/// </summary>
		/// <param name="Alignment">the alignment of the content</param>
		/// <param name="rect">rectagular region to place content</param>
		/// <param name="nWidth">with of content</param>
		/// <param name="nHeight">height of content</param>
		/// <returns>returns the left/top edge to place content</returns>
		private System.Drawing.Point Calculate_LeftEdgeTopEdge(System.Drawing.ContentAlignment Alignment, System.Drawing.Rectangle rect, int nWidth, int nHeight)
		{
			System.Drawing.Point pt = new System.Drawing.Point(0, 0);
			switch (Alignment)
			{
				case System.Drawing.ContentAlignment.BottomCenter:
					pt.X = (rect.Width - nWidth)/2;
					pt.Y = rect.Height - nHeight;
					break;
				case System.Drawing.ContentAlignment.BottomLeft:
					pt.X = 0;
					pt.Y = rect.Height - nHeight;
					break;
				case System.Drawing.ContentAlignment.BottomRight:
					pt.X = rect.Width - nWidth;
					pt.Y = rect.Height - nHeight;
					break;
				case System.Drawing.ContentAlignment.MiddleCenter:
					pt.X = (rect.Width - nWidth)/2;
					pt.Y = (rect.Height - nHeight)/2;
					break;
				case System.Drawing.ContentAlignment.MiddleLeft:
					pt.X = 0;
					pt.Y = (rect.Height - nHeight)/2;
					break;
				case System.Drawing.ContentAlignment.MiddleRight:
					pt.X = rect.Width - nWidth;
					pt.Y = (rect.Height - nHeight)/2;
					break;
				case System.Drawing.ContentAlignment.TopCenter:
					pt.X = (rect.Width - nWidth)/2;
					pt.Y = 0;
					break;
				case System.Drawing.ContentAlignment.TopLeft:
					pt.X = 0;
					pt.Y = 0;
					break;
				case System.Drawing.ContentAlignment.TopRight:
					pt.X = rect.Width - nWidth;
					pt.Y = 0;
					break;
			}
			pt.X += rect.Left;
			pt.Y += rect.Top;
			return (pt);
		}

		/// <summary>
		/// creates the region for the control. The region will have curved edges. 
		/// This prevents any drawing outside of the region.
		/// </summary>
		private void CreateRegion(int nContract)
		{
			Point[] points = border_Get(0, 0, this.Width, this.Height);
			border_Contract(nContract, ref points);
			System.Drawing.Drawing2D.GraphicsPath path = new System.Drawing.Drawing2D.GraphicsPath();
			path.AddLines(points);
			this.Region = new Region(path);
		}

		/// <summary>
		/// contract the array of points that define the border.
		/// </summary>
		/// <param name="nPixel">number of pixels to conract</param>
		/// <param name="pts">array of points that define the border</param>
		private void border_Contract(int nPixel, ref Point[] pts)
		{
			int a = nPixel;
			pts[0].X += a;
			pts[0].Y += a;
			pts[1].X -= a;
			pts[1].Y += a;
			pts[2].X -= a;
			pts[2].Y += a;
			pts[3].X -= a;
			pts[3].Y += a;
			pts[4].X -= a;
			pts[4].Y -= a;
			pts[5].X -= a;
			pts[5].Y -= a;
			pts[6].X -= a;
			pts[6].Y -= a;
			pts[7].X += a;
			pts[7].Y -= a;
			pts[8].X += a;
			pts[8].Y -= a;
			pts[9].X += a;
			pts[9].Y -= a;
			pts[10].X += a;
			pts[10].Y += a;
			pts[11].X += a;
			pts[10].Y += a;
		}

		/// <summary>
		/// calculates the array of points that make up a border
		/// </summary>
		/// <param name="nLeftEdge">left edge of border</param>
		/// <param name="nTopEdge">top edge of border</param>
		/// <param name="nWidth">width of border</param>
		/// <param name="nHeight">height of border</param>
		/// <returns>returns an array of points that make up the border</returns>
		private Point[] border_Get(int nLeftEdge, int nTopEdge, int nWidth, int nHeight)
		{
			int X = nWidth;
			int Y = nHeight;
			Point[] points =
				{
					new Point(1, 0),
					new Point(X - 1, 0),
					new Point(X - 1, 1),
					new Point(X, 1),
					new Point(X, Y - 1),
					new Point(X - 1, Y - 1),
					new Point(X - 1, Y),
					new Point(1, Y),
					new Point(1, Y - 1),
					new Point(0, Y - 1),
					new Point(0, 1),
					new Point(1, 1)
				};
			for (int i = 0; i < points.Length; i++)
				points[i].Offset(nLeftEdge, nTopEdge);
			return points;
		}

		/// <summary>
		/// Increments or decrements the red/green/blue values of a color. It enforces that the
		/// values do not go out of the bounds of 0..255
		/// </summary>
		/// <param name="SColor">source color</param>
		/// <param name="RED">red shift</param>
		/// <param name="GREEN">green shift</param>
		/// <param name="BLUE">blue shift</param>
		/// <returns>returns the calculated color</returns>
		private static Color Shade(Color SColor, int RED, int GREEN, int BLUE)
		{
			int r = SColor.R;
			int g = SColor.G;
			int b = SColor.B;

			r += RED;
			if (r > 0xFF) r = 0xFF;
			if (r < 0) r = 0;

			g += GREEN;
			if (g > 0xFF) g = 0xFF;
			if (g < 0) g = 0;

			b += BLUE;
			if (b > 0xFF) b = 0xFF;
			if (b < 0) b = 0;

			return Color.FromArgb(r, g, b);
		}

		/// <summary>
		/// Calculates a blended color using the specified parameters. 
		/// </summary>
		/// <param name="SColor">Source Color (color moving from)</param>
		/// <param name="DColor">Dest Color (color movving towards)</param>
		/// <param name="Percentage">Percentage of Dest Color (0..100)</param>
		/// <returns></returns>
		private static Color Blend(Color SColor, Color DColor, int Percentage)
		{
			int r = SColor.R + ((DColor.R - SColor.R)*Percentage)/100;
			int g = SColor.G + ((DColor.G - SColor.G)*Percentage)/100;
			int b = SColor.B + ((DColor.B - SColor.B)*Percentage)/100;
			return Color.FromArgb(r, g, b);
		}

		#endregion

		#region Events Methods

		/// <summary>
		/// Mouse Down Event:
		/// set BtnState to Pushed and Capturing mouse to true
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseDown(MouseEventArgs e)
		{
			base.OnMouseDown(e);
			this.Capture = true;
			this.CapturingMouse = true;
			btnState = BtnState.Pushed;
			this.Invalidate();
		}

		/// <summary>
		/// Mouse Up Event:
		/// Set BtnState to Normal and set CapturingMouse to false
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseUp(MouseEventArgs e)
		{
			base.OnMouseUp(e);
			btnState = BtnState.Normal;
			this.Invalidate();
			this.CapturingMouse = false;
			this.Capture = false;
			this.Invalidate();
		}

		/// <summary>
		/// Mouse Leave Event:
		/// Set BtnState to normal if we CapturingMouse = true
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseLeave(EventArgs e)
		{
			base.OnMouseLeave(e);
			if (!CapturingMouse)
			{
				btnState = BtnState.Normal;
				this.Invalidate();
			}
		}

		/// <summary>
		/// Mouse Move Event:
		/// If CapturingMouse = true and mouse coordinates are within button region, 
		/// set BtnState to Pushed, otherwise set BtnState to Normal.
		/// If CapturingMouse = false, then set BtnState to MouseOver
		/// </summary>
		/// <param name="e"></param>
		protected override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove(e);
			if (CapturingMouse)
			{
				System.Drawing.Rectangle rect = new System.Drawing.Rectangle(0, 0, this.Width, this.Height);
				btnState = BtnState.Normal;
				if ((e.X >= rect.Left) && (e.X <= rect.Right))
				{
					if ((e.Y >= rect.Top) && (e.Y <= rect.Bottom))
						btnState = BtnState.Pushed;
				}
				this.Capture = true;
				this.Invalidate();
			}
			else
			{
				//if(!this.Focused)
				{
					if (btnState != BtnState.MouseOver)
					{
						btnState = BtnState.MouseOver;
						this.Invalidate();
					}
				}
			}
		}

		/// <summary>
		/// Enable/Disable Event:
		/// If button became enabled, set BtnState to Normal
		/// else set BtnState to Inactive
		/// </summary>
		/// <param name="e"></param>
		protected override void OnEnabledChanged(EventArgs e)
		{
			base.OnEnabledChanged(e);
			if (this.Enabled)
				this.btnState = BtnState.Normal;
			else
				this.btnState = BtnState.Inactive;
			this.Invalidate();
		}

		/// <summary>
		/// Lose Focus Event:
		/// set btnState to Normal
		/// </summary>
		/// <param name="e"></param>
		protected override void OnLostFocus(EventArgs e)
		{
			base.OnLostFocus(e);
			if (this.Enabled)
				this.btnState = BtnState.Normal;
			this.Invalidate();
		}

		#endregion	
	}
}